using System.Linq;
using System;
using System.Collections.Generic;
using System.Text;
using T.FAS.Runtime.DataAccess.SPI;
using T.FAS.Runtime.DataAccess.SQLDom;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.DataAccess.Kernel;
using T.FAS.Runtime.DataAccess.Common;

namespace T.FAS.Runtime.DataAccess.Engine
{
    class DOQueryService : IQueryService<DataObject>
    {
        public event ExecuteDataAccessAction Execute;
        public event BuildDataAccessActionContext BuildContext;

        /// <summary>
        /// 查询指定的数据
        /// </summary>
        /// <param name="t">元数据</param>
        /// <param name="dataId">数据唯一标识</param>
        /// <returns>通用结果对象</returns>
        public TResult QueryData(DataObject metaData, string dataId, Dictionary<string, object> exrParams = null)
        {
            if (metaData == null)
                throw new FasException(DataAccessErrorCode.DataObject.NullValue, CommonStringClassEngine.DataModelService_MetaDataCannotBeNull);
            if (string.IsNullOrWhiteSpace(dataId))
                throw new FasException(DataAccessErrorCode.DataObject.NullValue, CommonStringClassEngine.DataModelService_DataIDCannotBeNull);

            var cdo = CDOConverter.Convert(metaData);
            var sqls = SQLBuilderFactory.CreateCDOSQLBuilder().ParseQuerySqlByID(cdo, dataId);

            var db = Kernel.DatabaseFactory.CreateDefaultDatabase();
            var datatable = db.GetDataCollection(sqls);

            return TResultConverter.ConvertToTResultFromDO(metaData, datatable);
        }

        /// <summary>
        /// 综合查询数据
        /// </summary>        
        /// <param name="metadata">元数据</param>        
        /// <param name="queryFilter">查询条件</param>        
        /// <returns>通用结果对象</returns>
        public TResult QueryData(DataObject metaData, QueryFilter queryFilter, Dictionary<string, object> exrParams = null)
        {
            if (metaData == null)
                throw new FasException(DataAccessErrorCode.DataObject.NullValue, CommonStringClassEngine.DataModelService_MetaDataCannotBeNull);
            if (queryFilter == null)
                throw new FasException(DataAccessErrorCode.DataObject.NullValue, CommonStringClassEngine.DataModelService_FilterCannotBeNull);

            var cdo = CDOConverter.Convert(metaData);
            var sqls = SQLBuilderFactory.CreateCDOSQLBuilder().ParseQuerySqlByFilter(cdo, queryFilter);

            var db = Kernel.DatabaseFactory.CreateDefaultDatabase();
            var datatable = db.GetDataCollection(sqls);

            return TResultConverter.ConvertToTResultFromDO(metaData, datatable);
        }

        /// <summary>
        /// 获取对象数据
        /// </summary>            
        /// <param name="metadata">元数据</param>
        /// <param name="childNodeId">节点ID</param>
        /// <param name="dataId">数据唯一标识</param>        
        /// <returns>通用结果对象</returns>
        public TResult QueryData(DataObject metaData, string childNodeId, string dataId, Dictionary<string, object> exrParams = null)
        {
            if (metaData == null)
                throw new FasException(DataAccessErrorCode.DataObject.NullValue, CommonStringClassEngine.DataModelService_MetaDataCannotBeNull);
            if (string.IsNullOrWhiteSpace(dataId))
                throw new FasException(DataAccessErrorCode.DataObject.NullValue, CommonStringClassEngine.DataModelService_DataIDCannotBeNull);
            
            var cdo = CDOConverter.Convert(metaData);
            var cno = cdo.CompositeNodeObjects.FirstOrDefault(i => i.ID == childNodeId);
            if (cno == null)
            {
                throw new FasException(DataAccessErrorCode.DataObject.NullValue, CommonStringClassEngine.CDOService_CannotFindCNOInstance + childNodeId);
            }

            var sqls = SQLBuilderFactory.CreateCDOSQLBuilder().ParseQuerySqlByID(cdo, cno, dataId);

            var db = Kernel.DatabaseFactory.CreateDefaultDatabase();
            var datatable = db.GetDataCollection(sqls);

            return TResultConverter.ConvertToTResultFromDO(metaData, datatable);
        }

        /// <summary>
        /// 获取对象数据
        /// </summary>        
        /// <param name="metadata">元数据</param>
        /// <param name="childNodeId">节点ID</param>
        /// <param name="queryFilter">查询条件</param>
        /// <returns>通用结果对象</returns>
        public TResult QueryData(DataObject metaData, string childNodeId, QueryFilter queryFilter, Dictionary<string, object> exrParams = null)
        {
            if (metaData == null)
                throw new FasException(DataAccessErrorCode.DataObject.NullValue, CommonStringClassEngine.DataModelService_MetaDataCannotBeNull);
            if (queryFilter == null)
                throw new FasException(DataAccessErrorCode.DataObject.NullValue, CommonStringClassEngine.DataModelService_FilterCannotBeNull);

            var cdo = CDOConverter.Convert(metaData);
            var cno = cdo.CompositeNodeObjects.FirstOrDefault(i => i.ID == childNodeId);
            if (cno == null)
            {
                throw new FasException(DataAccessErrorCode.DataObject.NullValue, CommonStringClassEngine.CDOService_CannotFindCNOInstance + childNodeId);
            }

            var sqls = SQLBuilderFactory.CreateCDOSQLBuilder().ParseQuerySqlByFilter(cdo, cno, queryFilter);

            var db = Kernel.DatabaseFactory.CreateDefaultDatabase();
            var datatable = db.GetDataCollection(sqls);

            return TResultConverter.ConvertToTResultFromDO(metaData, datatable);
        }
    }
}
